home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 3 / Gold Medal Software - Volume 3 (Gold Medal) (1994).iso / bbsutils / smb_110a.arj / SMBLIB.C < prev    next >
C/C++ Source or Header  |  1994-03-27  |  29KB  |  949 lines

  1. /* SMBLIB.C */
  2.  
  3. #include "smblib.h"
  4.  
  5. /****************************************************************************/
  6. /* Open a message base of name 'smb_file'                                   */
  7. /* Opens files for READing messages or updating message indices only        */
  8. /****************************************************************************/
  9. int smb_open(int retry_time)
  10. {
  11.     int file;
  12.     char str[128];
  13.     smbhdr_t hdr;
  14.  
  15. sprintf(str,"%s.SHD",smb_file);
  16. if((file=open(str,O_RDWR|O_CREAT|O_BINARY|O_DENYNONE,S_IWRITE|S_IREAD))==-1
  17.     || (shd_fp=fdopen(file,"r+b"))==NULL) {
  18.     if(file!=-1)
  19.         close(file);
  20.     return(2); }
  21. setvbuf(shd_fp,NULL,_IOFBF,2*1024);
  22.  
  23. if(filelength(file)>=sizeof(smbhdr_t)) {
  24.     if(smb_locksmbhdr(retry_time)) {
  25.         fclose(shd_fp);
  26.         return(-1); }
  27.     memset(&hdr,0,sizeof(smbhdr_t));
  28.     fread(&hdr,sizeof(smbhdr_t),1,shd_fp);
  29.     if(memcmp(hdr.id,"SMB\x1a",4)) {
  30.         fclose(shd_fp);
  31.         return(-2); }
  32.     if(hdr.version<0x110) {         /* Compatibility check */
  33.         fclose(shd_fp);
  34.         return(-3); }
  35.     smb_unlocksmbhdr();
  36.     rewind(shd_fp); }
  37.  
  38. sprintf(str,"%s.SDT",smb_file);
  39. if((file=open(str,O_RDWR|O_CREAT|O_BINARY|O_DENYNONE,S_IWRITE|S_IREAD))==-1
  40.     || (sdt_fp=fdopen(file,"r+b"))==NULL) {
  41.     if(file!=-1)
  42.         close(file);
  43.     fclose(shd_fp);
  44.     return(1); }
  45. setvbuf(sdt_fp,NULL,_IOFBF,2*1024);
  46.  
  47. sprintf(str,"%s.SID",smb_file);
  48. if((file=open(str,O_RDWR|O_CREAT|O_BINARY|O_DENYNONE,S_IWRITE|S_IREAD))==-1
  49.     || (sid_fp=fdopen(file,"r+b"))==NULL) {
  50.     if(file!=-1)
  51.         close(file);
  52.     fclose(sdt_fp);
  53.     fclose(shd_fp);
  54.     return(3); }
  55. setvbuf(sid_fp,NULL,_IOFBF,2*1024);
  56.  
  57. return(0);
  58. }
  59.  
  60. /****************************************************************************/
  61. /* Opens the data block allocation table message base 'smb_file'            */
  62. /* Retrys for retry_time number of seconds                                    */
  63. /* Return 0 on success, non-zero otherwise                                    */
  64. /****************************************************************************/
  65. int smb_open_da(int retry_time)
  66. {
  67.     int file;
  68.     char str[128];
  69.     long start;
  70.  
  71. start=time(NULL);
  72. sprintf(str,"%s.SDA",smb_file);
  73. while(1) {
  74.     if((file=open(str,O_RDWR|O_CREAT|O_BINARY|O_DENYALL,S_IWRITE|S_IREAD))!=-1)
  75.         break;
  76.     if(errno!=EACCES)
  77.         return(-1);
  78.     if(time(NULL)-start>=retry_time)
  79.         return(-2); }
  80. if((sda_fp=fdopen(file,"r+b"))==NULL)
  81.     return(-3);
  82. setvbuf(sda_fp,NULL,_IOFBF,2*1024);
  83. return(0);
  84. }
  85.  
  86. /****************************************************************************/
  87. /* Opens the header block allocation table for message base 'smb_file'      */
  88. /* Retrys for retry_time number of seconds                                    */
  89. /* Return 0 on success, non-zero otherwise                                    */
  90. /****************************************************************************/
  91. int smb_open_ha(int retry_time)
  92. {
  93.     int file;
  94.     char str[128];
  95.     long start;
  96.  
  97. start=time(NULL);
  98. sprintf(str,"%s.SHA",smb_file);
  99. while(1) {
  100.     if((file=open(str,O_RDWR|O_CREAT|O_BINARY|O_DENYALL,S_IWRITE|S_IREAD))!=-1)
  101.         break;
  102.     if(errno!=EACCES)
  103.         return(-1);
  104.     if(time(NULL)-start>=retry_time)
  105.         return(-2); }
  106. if((sha_fp=fdopen(file,"r+b"))==NULL)
  107.     return(-3);
  108. setvbuf(sha_fp,NULL,_IOFBF,2*1024);
  109. return(0);
  110. }
  111.  
  112. /****************************************************************************/
  113. /* Truncates header file                                                    */
  114. /* Retrys for retry_time number of seconds                                    */
  115. /* Return 0 on success, non-zero otherwise                                    */
  116. /****************************************************************************/
  117. int smb_trunchdr(int retry_time)
  118. {
  119.     long start;
  120.  
  121. start=time(NULL);
  122. rewind(shd_fp);
  123. while(1) {
  124.     if(!chsize(fileno(shd_fp),0L))
  125.         break;
  126.     if(errno!=EACCES)
  127.         return(-1);
  128.     if(time(NULL)-start>=retry_time)        /* Time-out */
  129.         return(-2); }
  130. return(0);
  131. }
  132.  
  133. /*********************************/
  134. /* Message Base Header Functions */
  135. /*********************************/
  136.  
  137. /****************************************************************************/
  138. /* Attempts for retry_time number of seconds to lock the message base hdr    */
  139. /****************************************************************************/
  140. int smb_locksmbhdr(int retry_time)
  141. {
  142.     ulong start;
  143.  
  144. start=time(NULL);
  145. while(1) {
  146.     if(!lock(fileno(shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)))
  147.         return(0);
  148.     if(time(NULL)-start>=retry_time)
  149.         break; }
  150. return(-1);
  151. }
  152.  
  153. /****************************************************************************/
  154. /* Read the SMB header from the hader file and place into "status"          */
  155. /****************************************************************************/
  156. int smb_getstatus(smbstatus_t *status)
  157. {
  158.     char    str[128];
  159.  
  160. clearerr(shd_fp);
  161. fseek(shd_fp,sizeof(smbhdr_t),SEEK_SET);
  162. if(fread(status,1,sizeof(smbstatus_t),shd_fp)==sizeof(smbstatus_t))
  163.     return(0);
  164. return(1);
  165. }
  166.  
  167. /****************************************************************************/
  168. /* Writes message base header                                                */
  169. /****************************************************************************/
  170. int smb_putstatus(smbstatus_t status)
  171. {
  172.     int i;
  173.  
  174. clearerr(shd_fp);
  175. fseek(shd_fp,sizeof(smbhdr_t),SEEK_SET);
  176. i=fwrite(&status,1,sizeof(smbstatus_t),shd_fp);
  177. if(i==sizeof(smbstatus_t))
  178.     return(0);
  179. return(1);
  180. }
  181.  
  182. /****************************************************************************/
  183. /* Unlocks previously locks message base header                             */
  184. /****************************************************************************/
  185. int smb_unlocksmbhdr()
  186. {
  187. return(unlock(fileno(shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)));
  188. }
  189.  
  190. /********************************/
  191. /* Individual Message Functions */
  192. /********************************/
  193.  
  194. /****************************************************************************/
  195. /* Attempts for retry_time number of seconds to lock the header for 'msg'   */
  196. /****************************************************************************/
  197. int smb_lockmsghdr(smbmsg_t msg, int retry_time)
  198. {
  199.     ulong start;
  200.  
  201. start=time(NULL);
  202. while(1) {
  203.     if(!lock(fileno(shd_fp),msg.idx.offset,sizeof(msghdr_t)))
  204.         return(0);
  205.     if(time(NULL)-start>=retry_time)
  206.         break; }
  207. return(-1);
  208. }
  209.  
  210. /****************************************************************************/
  211. /* Fills msg->idx with message index based on msg->hdr.number                */
  212. /* OR if msg->hdr.number is 0, based on msg->offset (physical offset).        */
  213. /* if msg.hdr.number does not equal 0, then msg->offset is filled too.        */
  214. /* Either msg->hdr.number or msg->offset must be initialized before         */
  215. /* calling this function                                                    */
  216. /* Returns 1 if message number wasn't found, 0 if it was                    */
  217. /****************************************************************************/
  218. int smb_getmsgidx(smbmsg_t *msg)
  219. {
  220.     idxrec_t idx;
  221.     ulong     l,length,total,bot,top;
  222.  
  223. clearerr(sid_fp);
  224. if(!msg->hdr.number) {
  225.     fseek(sid_fp,msg->offset*sizeof(idxrec_t),SEEK_SET);
  226.     if(!fread(&msg->idx,sizeof(idxrec_t),1,sid_fp))
  227.         return(1);
  228.     return(0); }
  229.  
  230. length=filelength(fileno(sid_fp));
  231. if(!length)
  232.     return(1);
  233. total=length/sizeof(idxrec_t);
  234. if(!total)
  235.     return(1);
  236.  
  237. bot=0;
  238. top=total;
  239. l=total/2; /* Start at middle index */
  240. while(1) {
  241.     fseek(sid_fp,l*sizeof(idxrec_t),SEEK_SET);
  242.     if(!fread(&idx,sizeof(idxrec_t),1,sid_fp))
  243.         return(1);
  244.     if(bot==top-1 && idx.number!=msg->hdr.number)
  245.         return(1);
  246.     if(idx.number>msg->hdr.number) {
  247.         top=l;
  248.         l=bot+((top-bot)/2);
  249.         continue; }
  250.     if(idx.number<msg->hdr.number) {
  251.         bot=l;
  252.         l=top-((top-bot)/2);
  253.         continue; }
  254.     break; }
  255. msg->idx=idx;
  256. msg->offset=l;
  257. return(0);
  258. }
  259.  
  260. /****************************************************************************/
  261. /* Reads the last index record in the open message base                     */
  262. /****************************************************************************/
  263. int smb_getlastidx(idxrec_t *idx)
  264. {
  265.     long length;
  266.  
  267. clearerr(sid_fp);
  268. length=filelength(fileno(sid_fp));
  269. if(length<sizeof(idxrec_t))
  270.     return(-1);
  271. fseek(sid_fp,length-sizeof(idxrec_t),SEEK_SET);
  272. if(!fread(idx,sizeof(idxrec_t),1,sid_fp))
  273.     return(-2);
  274. return(0);
  275. }
  276.  
  277. /****************************************************************************/
  278. /* Figures out the total length of the header record for 'msg'              */
  279. /* Returns length                                                            */
  280. /****************************************************************************/
  281. int smb_getmsghdrlen(smbmsg_t msg)
  282. {
  283.     int i;
  284.  
  285. /* fixed portion */
  286. msg.hdr.length=sizeof(msghdr_t);
  287. /* data fields */
  288. msg.hdr.length+=msg.hdr.total_dfields*sizeof(dfield_t);
  289. /* header fields */
  290. for(i=0;i<msg.total_hfields;i++) {
  291.     msg.hdr.length+=sizeof(hfield_t);
  292.     msg.hdr.length+=msg.hfield[i].length; }
  293. return(msg.hdr.length);
  294. }
  295.  
  296. /****************************************************************************/
  297. /* Figures out the total length of the data buffer for 'msg'                */
  298. /* Returns length                                                            */
  299. /****************************************************************************/
  300. long smb_getmsgdatlen(smbmsg_t msg)
  301. {
  302.     int i;
  303.     ulong length=0L;
  304.  
  305. for(i=0;i<msg.hdr.total_dfields;i++)
  306.     length+=msg.dfield[i].length;
  307. return(length);
  308. }
  309.  
  310. /****************************************************************************/
  311. /* Read header information into 'msg' structure                             */
  312. /* msg->idx.offset must be set before calling this function                 */
  313. /* Must call smb_freemsgmem() to free memory allocated for var len strs     */
  314. /* Returns 0 on success, non-zero if error                                    */
  315. /****************************************************************************/
  316. int smb_getmsghdr(smbmsg_t *msg)
  317. {
  318.     ushort    i;
  319.     ulong    l,offset;
  320.     idxrec_t idx;
  321.  
  322. clearerr(shd_fp);
  323. fseek(shd_fp,msg->idx.offset,SEEK_SET);
  324. idx=msg->idx;
  325. offset=msg->offset;
  326. memset(msg,0,sizeof(smbmsg_t));
  327. msg->idx=idx;
  328. msg->offset=offset;
  329. if(!fread(&msg->hdr,sizeof(msghdr_t),1,shd_fp))
  330.     return(-1);
  331. if(memcmp(msg->hdr.id,"SHD\x1a",4))
  332.     return(-2);
  333. if(msg->hdr.version<0x110)
  334.     return(-9);
  335. l=sizeof(msghdr_t);
  336. if(msg->hdr.total_dfields && (msg->dfield
  337.     =(dfield_t *)MALLOC(sizeof(dfield_t)*msg->hdr.total_dfields))==NULL) {
  338.     smb_freemsgmem(*msg);
  339.     return(-3); }
  340. i=0;
  341. while(i<msg->hdr.total_dfields && l<msg->hdr.length) {
  342.     if(!fread(&msg->dfield[i],sizeof(dfield_t),1,shd_fp)) {
  343.         smb_freemsgmem(*msg);
  344.         return(-4); }
  345.     i++;
  346.     l+=sizeof(dfield_t); }
  347. if(i<msg->hdr.total_dfields) {
  348.     smb_freemsgmem(*msg);
  349.     return(-8); }
  350.  
  351. while(l<msg->hdr.length) {
  352.     i=msg->total_hfields;
  353.     if((msg->hfield_dat=(void **)REALLOC(msg->hfield_dat,sizeof(void *)*(i+1)))
  354.         ==NULL) {
  355.         smb_freemsgmem(*msg);
  356.         return(-3); }
  357.     if((msg->hfield=(hfield_t *)REALLOC(msg->hfield
  358.         ,sizeof(hfield_t)*(i+1)))==NULL) {
  359.         smb_freemsgmem(*msg);
  360.         return(-3); }
  361.     msg->total_hfields++;
  362.     if(!fread(&msg->hfield[i],sizeof(hfield_t),1,shd_fp)) {
  363.         smb_freemsgmem(*msg);
  364.         return(-5); }
  365.     l+=sizeof(hfield_t);
  366.     if((msg->hfield_dat[i]=(char *)MALLOC(msg->hfield[i].length+1))
  367.         ==NULL) {            /* Allocate 1 extra for NULL terminator */
  368.         smb_freemsgmem(*msg);  /* or 0 length field */
  369.         return(-3); }
  370.     memset(msg->hfield_dat[i],0,msg->hfield[i].length+1);  /* init to NULL */
  371.     if(msg->hfield[i].length
  372.         && !fread(msg->hfield_dat[i],msg->hfield[i].length,1,shd_fp)) {
  373.         smb_freemsgmem(*msg);
  374.         return(-6); }
  375.     switch(msg->hfield[i].type) {    /* convenience variables */
  376.         case SENDER:
  377.             msg->from=msg->hfield_dat[i];
  378.             break;
  379.         case SENDERAGENT:
  380.             msg->from_agent=*(ushort *)msg->hfield_dat[i];
  381.             break;
  382.         case SENDEREXT:
  383.             msg->from_ext=msg->hfield_dat[i];
  384.             break;
  385.         case SENDERNETTYPE:
  386.             msg->from_net.type=*(ushort *)msg->hfield_dat[i];
  387.             break;
  388.         case SENDERNETADDR:
  389.             msg->from_net.addr=msg->hfield_dat[i];
  390.             break;
  391.         case REPLYTO:
  392.             msg->replyto=msg->hfield_dat[i];
  393.             break;
  394.         case REPLYTOEXT:
  395.             msg->replyto_ext=msg->hfield_dat[i];
  396.             break;
  397.         case REPLYTOAGENT:
  398.             msg->replyto_agent=*(ushort *)msg->hfield_dat[i];
  399.             break;
  400.         case REPLYTONETTYPE:
  401.             msg->replyto_net.type=*(ushort *)msg->hfield_dat[i];
  402.             break;
  403.         case REPLYTONETADDR:
  404.             msg->replyto_net.addr=msg->hfield_dat[i];
  405.             break;
  406.         case RECIPIENT:
  407.             msg->to=msg->hfield_dat[i];
  408.             break;
  409.         case RECIPIENTEXT:
  410.             msg->to_ext=msg->hfield_dat[i];
  411.             break;
  412.         case RECIPIENTAGENT:
  413.             msg->to_agent=*(ushort *)msg->hfield_dat[i];
  414.             break;
  415.         case RECIPIENTNETTYPE:
  416.             msg->to_net.type=*(ushort *)msg->hfield_dat[i];
  417.             break;
  418.         case RECIPIENTNETADDR:
  419.             msg->to_net.addr=msg->hfield_dat[i];
  420.             break;
  421.         case SUBJECT:
  422.             msg->subj=msg->hfield_dat[i];
  423.             break; }
  424.     l+=msg->hfield[i].length; }
  425.  
  426. if(!msg->from || !msg->to || !msg->subj) {
  427.     smb_freemsgmem(*msg);
  428.     return(-7); }
  429. return(0);
  430. }
  431.  
  432. /****************************************************************************/
  433. /* Frees memory allocated for 'msg'                                         */
  434. /****************************************************************************/
  435. void smb_freemsgmem(smbmsg_t msg)
  436. {
  437.     ushort    i;
  438.  
  439. if(msg.dfield)
  440.     FREE(msg.dfield);
  441. for(i=0;i<msg.total_hfields;i++)
  442.     if(msg.hfield_dat[i])
  443.         FREE(msg.hfield_dat[i]);
  444. if(msg.hfield)
  445.     FREE(msg.hfield);
  446. if(msg.hfield_dat)
  447.     FREE(msg.hfield_dat);
  448. }
  449.  
  450. /****************************************************************************/
  451. /* Unlocks header for 'msg'                                                 */
  452. /****************************************************************************/
  453. int smb_unlockmsghdr(smbmsg_t msg)
  454. {
  455. return(unlock(fileno(shd_fp),msg.idx.offset,sizeof(msghdr_t)));
  456. }
  457.  
  458.  
  459. /****************************************************************************/
  460. /* Adds an header field to the 'msg' structure (in memory only)             */
  461. /****************************************************************************/
  462. int smb_hfield(smbmsg_t *msg, ushort type, ushort length, void *data)
  463. {
  464.     int i;
  465.  
  466. i=msg->total_hfields;
  467. if((msg->hfield=(hfield_t *)REALLOC(msg->hfield,sizeof(hfield_t)*(i+1)))
  468.     ==NULL)
  469.     return(1);
  470. if((msg->hfield_dat=(void **)REALLOC(msg->hfield_dat,sizeof(void *)*(i+1)))
  471.     ==NULL)
  472.     return(2);
  473. msg->total_hfields++;
  474. msg->hfield[i].type=type;
  475. msg->hfield[i].length=length;
  476. if(length) {
  477.     if((msg->hfield_dat[i]=(void *)MALLOC(length))==NULL)
  478.         return(4);
  479.     memcpy(msg->hfield_dat[i],data,length); }
  480. else
  481.     msg->hfield_dat[i]=NULL;
  482. return(0);
  483. }
  484.  
  485. /****************************************************************************/
  486. /* Adds a data field to the 'msg' structure (in memory only)                */
  487. /* Automatically figures out the offset into the data buffer from existing    */
  488. /* dfield lengths                                                            */
  489. /****************************************************************************/
  490. int smb_dfield(smbmsg_t *msg, ushort type, ulong length)
  491. {
  492.     int i,j;
  493.  
  494. i=msg->hdr.total_dfields;
  495. if((msg->dfield=(dfield_t *)REALLOC(msg->dfield,sizeof(dfield_t)*(i+1)))
  496.     ==NULL)
  497.     return(1);
  498. msg->hdr.total_dfields++;
  499. msg->dfield[i].type=type;
  500. msg->dfield[i].length=length;
  501. for(j=msg->dfield[i].offset=0;j<i;j++)
  502.     msg->dfield[i].offset+=msg->dfield[j].length;
  503. return(0);
  504. }
  505.  
  506. /****************************************************************************/
  507. /* Checks CRC history file for duplicate crc. If found, returns 1.            */
  508. /* If no dupe, adds to CRC history and returns 0, or negative if error.     */
  509. /****************************************************************************/
  510. int smb_addcrc(ulong max_crcs, ulong crc, int retry_time)
  511. {
  512.     char    str[128];
  513.     int     file;
  514.     long    length;
  515.     ulong    l,*buf;
  516.     time_t    start;
  517.  
  518. if(!max_crcs)
  519.     return(0);
  520. start=time(NULL);
  521. sprintf(str,"%s.SCH",smb_file);
  522. while(1) {
  523.     if((file=open(str,O_RDWR|O_CREAT|O_BINARY|O_DENYALL,S_IWRITE|S_IREAD))!=-1)
  524.         break;
  525.     if(errno!=EACCES)
  526.         return(-1);
  527.     if(time(NULL)-start>=retry_time)
  528.         return(-2); }
  529. length=filelength(file);
  530. if(length<0L) {
  531.     close(file);
  532.     return(-4); }
  533. if((buf=(ulong *)MALLOC(max_crcs*4))==NULL) {
  534.     close(file);
  535.     return(-3); }
  536. if(length>=max_crcs*4) {            /* Reached or exceeds max crcs */
  537.     read(file,buf,max_crcs*4);
  538.     for(l=0;l<max_crcs;l++)
  539.         if(crc==buf[l])
  540.             break;
  541.     if(l<max_crcs) {                /* Dupe CRC found */
  542.         close(file);
  543.         FREE(buf);
  544.         return(1); }
  545.     chsize(file,0L);                /* truncate it */
  546.     lseek(file,0L,SEEK_SET);
  547.     write(file,buf+4,(max_crcs-1)*4); }
  548.  
  549. else if(length/4) {                         /* Less than max crcs */
  550.     read(file,buf,length);
  551.     for(l=0;l<length/4;l++)
  552.         if(crc==buf[l])
  553.             break;
  554.     if(l<length/4) {                    /* Dupe CRC found */
  555.         close(file);
  556.         FREE(buf);
  557.         return(1); } }
  558.  
  559. lseek(file,0L,SEEK_END);
  560. write(file,&crc,4);                /* Write to the end */
  561. FREE(buf);
  562. close(file);
  563. return(0);
  564. }
  565.  
  566.  
  567. /****************************************************************************/
  568. /* Creates a new message header record in the header file.                    */
  569. /* If 'fast' is non-zero, fast index allocation will be used.               */
  570. /* msg.idx.offset must be initialized to the offset of the first header     */
  571. /* record before calling this function                                        */
  572. /****************************************************************************/
  573. int smb_addmsghdr(smbmsg_t *msg, smbstatus_t *status, int fast, int retry_time)
  574. {
  575.     int i;
  576.     long l;
  577.  
  578. if(smb_locksmbhdr(retry_time))
  579.     return(1);
  580. if(smb_getstatus(status))
  581.     return(2);
  582.  
  583. if((i=smb_open_ha(retry_time))!=0)
  584.     return(i);
  585.  
  586. msg->hdr.length=smb_getmsghdrlen(*msg);
  587. if(fast)
  588.     l=smb_fallochdr(msg->hdr.length);
  589. else
  590.     l=smb_allochdr(msg->hdr.length);
  591. if(l==-1L) {
  592.     smb_unlocksmbhdr();
  593.     fclose(sha_fp);
  594.     return(-1); }
  595.  
  596. status->last_msg++;
  597. msg->idx.number=msg->hdr.number=status->last_msg;
  598. msg->idx.offset=status->header_offset+l;
  599. msg->idx.time=msg->hdr.when_imported.time;
  600. msg->offset=status->total_msgs;
  601. status->total_msgs++;
  602. smb_putstatus(*status);
  603.  
  604. fclose(sha_fp);
  605. i=smb_putmsg(*msg);
  606. smb_unlocksmbhdr();
  607. return(i);
  608. }
  609.  
  610. /****************************************************************************/
  611. /* Writes both header and index information for msg 'msg'                   */
  612. /****************************************************************************/
  613. int smb_putmsg(smbmsg_t msg)
  614. {
  615.     int i;
  616.  
  617. i=smb_putmsghdr(msg);
  618. if(i)
  619.     return(i);
  620. return(smb_putmsgidx(msg));
  621. }
  622.  
  623. /****************************************************************************/
  624. /* Writes index information for 'msg'                                       */
  625. /* msg.idx                                                                    */
  626. /* and msg.offset must be set prior to calling to this function             */
  627. /* Returns 0 if everything ok                                               */
  628. /****************************************************************************/
  629. int smb_putmsgidx(smbmsg_t msg)
  630. {
  631.  
  632. clearerr(sid_fp);
  633. fseek(sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
  634. if(!fwrite(&msg.idx,sizeof(idxrec_t),1,sid_fp))
  635.     return(1);
  636. return(0);
  637. }
  638.  
  639. /****************************************************************************/
  640. /* Writes header information for 'msg'                                      */
  641. /* msg.hdr.length                                                           */
  642. /* msg.idx.offset                                                           */
  643. /* and msg.offset must be set prior to calling to this function             */
  644. /* Returns 0 if everything ok                                               */
  645. /****************************************************************************/
  646. int smb_putmsghdr(smbmsg_t msg)
  647. {
  648.     ushort    i;
  649.     ulong    l;
  650.  
  651. clearerr(shd_fp);
  652. if(fseek(shd_fp,msg.idx.offset,SEEK_SET))
  653.     return(-1);
  654.  
  655. /************************************************/
  656. /* Write the fixed portion of the header record */
  657. /************************************************/
  658. if(!fwrite(&msg.hdr,sizeof(msghdr_t),1,shd_fp))
  659.     return(-2);
  660.  
  661. /************************************************/
  662. /* Write the data fields (each is fixed length) */
  663. /************************************************/
  664. for(i=0;i<msg.hdr.total_dfields;i++)
  665.     if(!fwrite(&msg.dfield[i],sizeof(dfield_t),1,shd_fp))
  666.         return(-3);
  667.  
  668. /*******************************************/
  669. /* Write the variable length header fields */
  670. /*******************************************/
  671. for(i=0;i<msg.total_hfields;i++) {
  672.     if(!fwrite(&msg.hfield[i],sizeof(hfield_t),1,shd_fp))
  673.         return(-4);
  674.     if(!fwrite(msg.hfield_dat[i],msg.hfield[i].length,1,shd_fp))
  675.         return(-5); }
  676.  
  677. l=smb_getmsghdrlen(msg);
  678. while(l%SHD_BLOCK_LEN) {
  679.     if(fputc(0,shd_fp)==EOF)
  680.         return(-6);                /* pad block with NULL */
  681.     l++; }
  682. return(0);
  683. }
  684.  
  685. /****************************************************************************/
  686. /* Creates a sub-board's initial header file                                */
  687. /* Truncates and deletes other associated SMB files                         */
  688. /****************************************************************************/
  689. int smb_create(ulong max_crcs, ulong max_msgs, ushort max_age, int retry_time)
  690. {
  691.     char        str[128];
  692.     smbhdr_t    hdr;
  693.     smbstatus_t status;
  694.  
  695. if(filelength(fileno(shd_fp))>=sizeof(smbhdr_t)+sizeof(smbstatus_t)
  696.     && smb_locksmbhdr(retry_time))    /* header exists, so lock it */
  697.     return(1);
  698. memset(&hdr,0,sizeof(smbhdr_t));
  699. memset(&status,0,sizeof(smbstatus_t));
  700. memcpy(hdr.id,"SMB\x1a",4);     // <S> <M> <B> <^Z>
  701. hdr.version=SMB_VERSION;
  702. hdr.length=sizeof(smbhdr_t)+sizeof(smbstatus_t);
  703. status.last_msg=status.total_msgs=0;
  704. status.header_offset=sizeof(smbhdr_t)+sizeof(smbstatus_t);
  705. status.max_crcs=max_crcs;
  706. status.max_msgs=max_msgs;
  707. status.max_age=max_age;
  708. rewind(shd_fp);
  709. fwrite(&hdr,1,sizeof(smbhdr_t),shd_fp);
  710. fwrite(&status,1,sizeof(smbstatus_t),shd_fp);
  711. rewind(shd_fp);
  712. chsize(fileno(shd_fp),sizeof(smbhdr_t)+sizeof(smbstatus_t));
  713.  
  714. rewind(sdt_fp);
  715. chsize(fileno(sdt_fp),0L);
  716. rewind(sid_fp);
  717. chsize(fileno(sid_fp),0L);
  718.  
  719. sprintf(str,"%s.SDA",smb_file);
  720. remove(str);                        /* if it exists, delete it */
  721. sprintf(str,"%s.SHA",smb_file);
  722. remove(str);                        /* if it exists, delete it */
  723. sprintf(str,"%s.SCH",smb_file);
  724. remove(str);
  725. smb_unlocksmbhdr();
  726. return(0);
  727. }
  728.  
  729. /****************************************************************************/
  730. /* Returns number of data blocks required to store "length" amount of data  */
  731. /****************************************************************************/
  732. long smb_datblocks(ulong length)
  733. {
  734.     ulong blocks;
  735.  
  736. blocks=length/SDT_BLOCK_LEN;
  737. if(length%SDT_BLOCK_LEN)
  738.     blocks++;
  739. return(blocks);
  740. }
  741.  
  742. /****************************************************************************/
  743. /* Returns number of header blocks required to store "length" size header   */
  744. /****************************************************************************/
  745. long smb_hdrblocks(ulong length)
  746. {
  747.     ulong blocks;
  748.  
  749. blocks=length/SHD_BLOCK_LEN;
  750. if(length%SHD_BLOCK_LEN)
  751.     blocks++;
  752. return(blocks);
  753. }
  754.  
  755. /****************************************************************************/
  756. /* Finds unused space in data file based on block allocation table and        */
  757. /* marks space as used in allocation table.                                 */
  758. /* File must be opened read/write DENY ALL                                    */
  759. /* Returns offset to beginning of data (in bytes, not blocks)                */
  760. /* Assumes smb_open_da() has been called                                    */
  761. /* fclose(sda_fp) should be called after                                    */
  762. /* Returns negative on error                                                */
  763. /****************************************************************************/
  764. long smb_allocdat(ulong length, ushort headers)
  765. {
  766.     ushort  i,j;
  767.     ulong    l,blocks,offset=0L;
  768.  
  769. blocks=smb_datblocks(length);
  770. j=0;    /* j is consecutive unused block counter */
  771. rewind(sda_fp);
  772. while(!feof(sda_fp)) {
  773.     if(!fread(&i,2,1,sda_fp))
  774.         break;
  775.     offset+=SDT_BLOCK_LEN;
  776.     if(!i) j++;
  777.     else   j=0;
  778.     if(j==blocks) {
  779.         offset-=(blocks*SDT_BLOCK_LEN);
  780.         break; } }
  781. clearerr(sda_fp);
  782. fseek(sda_fp,(offset/SDT_BLOCK_LEN)*2L,SEEK_SET);
  783. for(l=0;l<blocks;l++)
  784.     if(!fwrite(&headers,2,1,sda_fp))
  785.         return(-1);
  786. return(offset);
  787. }
  788.  
  789. /****************************************************************************/
  790. /* Allocates space for data, but doesn't search for unused blocks           */
  791. /* Returns negative on error                                                */
  792. /****************************************************************************/
  793. long smb_fallocdat(ulong length, ushort headers)
  794. {
  795.     ulong    l,blocks,offset=0L;
  796.  
  797. clearerr(sda_fp);
  798. blocks=smb_datblocks(length);
  799. fseek(sda_fp,0L,SEEK_END);
  800. offset=(ftell(sda_fp)/2L)*SDT_BLOCK_LEN;
  801. for(l=0;l<blocks;l++)
  802.     if(!fwrite(&headers,2,1,sda_fp))
  803.         break;
  804. if(l<blocks)
  805.     return(-1L);
  806. return(offset);
  807. }
  808.  
  809. /****************************************************************************/
  810. /* De-allocates space for data                                                */
  811. /* Returns non-zero on error                                                */
  812. /****************************************************************************/
  813. int smb_freemsgdat(ulong offset, ulong length, ushort headers)
  814. {
  815.     ushort    i;
  816.     ulong    l,blocks;
  817.  
  818. blocks=smb_datblocks(length);
  819.  
  820. clearerr(sda_fp);
  821. for(l=0;l<blocks;l++) {
  822.     if(fseek(sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET))
  823.         return(1);
  824.     if(!fread(&i,2,1,sda_fp))
  825.         return(2);
  826.     if(headers>i)
  827.         i=0;            /* don't want to go negative */
  828.     else
  829.         i-=headers;
  830.     if(fseek(sda_fp,-2L,SEEK_CUR))
  831.         return(3);
  832.     if(!fwrite(&i,2,1,sda_fp))
  833.         return(4); }
  834. return(0);
  835. }
  836.  
  837. /****************************************************************************/
  838. /* Adds to data allocation records for blocks starting at 'offset'          */
  839. /* Returns non-zero on error                                                */
  840. /****************************************************************************/
  841. int smb_incdat(ulong offset, ulong length, ushort headers)
  842. {
  843.     ushort    i;
  844.     ulong    l,blocks;
  845.  
  846. clearerr(sda_fp);
  847. blocks=smb_datblocks(length);
  848. for(l=0;l<blocks;l++) {
  849.     fseek(sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET);
  850.     if(!fread(&i,2,1,sda_fp))
  851.         return(1);
  852.     i+=headers;
  853.     fseek(sda_fp,-2L,SEEK_CUR);
  854.     if(!fwrite(&i,2,1,sda_fp))
  855.         return(2); }
  856. return(0);
  857. }
  858.  
  859. /****************************************************************************/
  860. /* De-allocates blocks for header record                                    */
  861. /* Returns non-zero on error                                                */
  862. /****************************************************************************/
  863. int smb_freemsghdr(ulong offset, ulong length)
  864. {
  865.     uchar    c=0;
  866.     ulong    l,blocks;
  867.  
  868. clearerr(sha_fp);
  869. blocks=smb_hdrblocks(length);
  870. fseek(sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
  871. for(l=0;l<blocks;l++)
  872.     if(!fwrite(&c,1,1,sha_fp))
  873.         return(1);
  874. return(0);
  875. }
  876.  
  877. /****************************************************************************/
  878. /* Frees all allocated header and data blocks for 'msg'                     */
  879. /****************************************************************************/
  880. int smb_freemsg(smbmsg_t msg, smbstatus_t status)
  881. {
  882.     int     i;
  883.     ushort    x;
  884.  
  885. for(x=0;x<msg.hdr.total_dfields;x++) {
  886.     if((i=smb_freemsgdat(msg.hdr.offset+msg.dfield[x].offset
  887.         ,msg.dfield[x].length,1))!=0)
  888.         return(i); }
  889. return(smb_freemsghdr(msg.idx.offset-status.header_offset,msg.hdr.length));
  890. }
  891.  
  892. /****************************************************************************/
  893. /* Finds unused space in header file based on block allocation table and    */
  894. /* marks space as used in allocation table.                                 */
  895. /* File must be opened read/write DENY ALL                                    */
  896. /* Returns offset to beginning of header (in bytes, not blocks)             */
  897. /* Assumes smb_open_ha() has been called                                    */
  898. /* fclose(sha_fp) should be called after                                    */
  899. /* Returns -1L on error                                                     */
  900. /****************************************************************************/
  901. long smb_allochdr(ulong length)
  902. {
  903.     uchar    c;
  904.     ushort    i;
  905.     ulong    l,blocks,offset=0;
  906.  
  907. blocks=smb_hdrblocks(length);
  908. i=0;    /* i is consecutive unused block counter */
  909. rewind(sha_fp);
  910. while(!feof(sha_fp)) {
  911.     if(!fread(&c,1,1,sha_fp))
  912.         break;
  913.     offset+=SHD_BLOCK_LEN;
  914.     if(!c) i++;
  915.     else   i=0;
  916.     if(i==blocks) {
  917.         offset-=(blocks*SHD_BLOCK_LEN);
  918.         break; } }
  919. clearerr(sha_fp);
  920. fseek(sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
  921. c=1;
  922. for(l=0;l<blocks;l++)
  923.     if(!fwrite(&c,1,1,sha_fp))
  924.         return(-1L);
  925. return(offset);
  926. }
  927.  
  928. /****************************************************************************/
  929. /* Allocates space for index, but doesn't search for unused blocks          */
  930. /* Returns -1L on error                                                     */
  931. /****************************************************************************/
  932. long smb_fallochdr(ulong length)
  933. {
  934.     uchar    c=1;
  935.     ulong    l,blocks,offset=0L;
  936.  
  937. blocks=smb_hdrblocks(length);
  938. clearerr(sha_fp);
  939. fseek(sha_fp,0L,SEEK_END);
  940. offset=ftell(sha_fp)*SHD_BLOCK_LEN;
  941. for(l=0;l<blocks;l++)
  942.     if(!fwrite(&c,1,1,sha_fp))
  943.         return(-1L);
  944. return(offset);
  945. }
  946.  
  947.  
  948. /* End of SMBLIB.C */
  949.